/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Dao;

import java.util.ArrayList;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import util.HibernateUtil;

/**
 *
 * @author mayra
 */
public class Dao<M>  {

    //alguns métodos necessitam do nome da classe ex.: criteria
    private Class<M> nomeDaClasse;
    

    public Dao() {


    }

    protected void setNomeDaClasse(Class nomeDaClasse) {
        this.nomeDaClasse = nomeDaClasse;
    }

    /*protected só pode ser acessado dentro desse pacote */
    protected Session abrirSessao() {
        SessionFactory sf = HibernateUtil.getSessionFactory();
        Session sessao = sf.openSession();
        return sessao;
    }

    public void adicionar(M objeto) throws  Exception {
        Session session = null;
        try {
            session = abrirSessao();
            Transaction transaction = session.beginTransaction();
            session.save(objeto);

            transaction.commit();
        } catch (HibernateException e) {
            throw  new Exception("Erro ao adicionar");
        }

    }

    /*
    a diferença de List para Set
     * que o segundo nao aceita repetir objetos
     * isso quer dizer que se vc adicionar o mesmo objeto duas
     * vezes ela só adiciona a primeira
     */
    public List<M> lista() {
        List<M> retorno = new ArrayList<M>();

        Session sessao = null;

        try {
            sessao = abrirSessao();
            /*cria uma criteria, criteria é uma busca avançada no banco de
            dados, existe 3 tipos de busca,
            primerio com o metodos já existentes: get, merge
            segundo com query é tipo um sql só que para o hibernate
            terceiro criteria uma busca orientada a objeto
            qualquer ajuda com criteria http://docs.jboss.org/hibernate/core/3.3/reference/en/html/querycriteria.html*/

            retorno = sessao.createCriteria(nomeDaClasse).list();
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }

        if(retorno == null){
             retorno = new ArrayList<M>();
        }
        return retorno;
    }

    public List<M> lista(Class classe){
        List<M> retorno = new ArrayList<M>();
        Session sessao = abrirSessao();
        Query query = sessao.createQuery("select T  from "+ classe.getSimpleName()+" T");
        retorno = query.list();
        return retorno;
    }

    /**
     *Método que traz uma listagem passando
     * a quantidade de registro por parametro
     *
     */
    public List<M> lista(Integer quantidade) {
        List<M> retorno = new ArrayList<M>();

        Session sessao = null;

        try {
            sessao = abrirSessao();
            /*cria uma criteria, criteria é uma busca avançada no banco de
            dados, existe 3 tipos de busca,
            primerio com o metodos já existentes: get, merge
            segundo com query é tipo um sql só que para o hibernate
            terceiro criteria uma busca orientada a objeto
            qualquer ajuda com criteria http://docs.jboss.org/hibernate/core/3.3/reference/en/html/querycriteria.html*/

            retorno = sessao.createCriteria(this.nomeDaClasse).setMaxResults(quantidade).list();
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }
        return retorno;
    }

    public void deletar(M objeto) throws Exception {
        Session sessao = null;
        try {
            sessao = abrirSessao();

            sessao.delete(objeto);
            /*SE DER ERRO AO EXCLUIR LANCA HibernateException, caso ocorra
            será lancada a excessao NegocioException*/
        } catch (HibernateException ex) {
            throw new Exception("Erro ao excluir");
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }


    }

    public M getObjeto(Long id) {

        Session sessao = null;
        M retorno = null;
        
            sessao = abrirSessao();
            retorno = (M) sessao.get(this.nomeDaClasse, 1l);
        
        return retorno;
    }

    public void atualizar(M objeto) {

        Session sessao = null;

        try {
            sessao = abrirSessao();
            Transaction transaction = sessao.beginTransaction();
            /*merge é para update mas se não existir o objeto ele faz o insert*/
            sessao.merge(objeto);

            /*para salvar ou efetuar uma alteração no banco é
            necessário fazer o commit*/
            transaction.commit();
        } finally {
            if (sessao != null) {

                sessao.close();
            }

        }

    }

    public Class getNomeDaClasse() {
        return nomeDaClasse;
    }
}
